package com.eagle.svnkit;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

import org.tmatesoft.svn.core.SVNDirEntry;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
/**
  * SVNManager SVN管理器
  */
public class SVNManager{
        private String url;
        private String username;
        private String password;
        private SVNRepository repository;
            
        public SVNManager(String url, String username, String password) {
                super();
                this.url = url;
                this.username = username;
                this.password = password;
                initialize();
            }
            /**
      * 初始化操作
      * @throws SVNException
      */
            private void initialize() {
                FSRepositoryFactory.setup();
                DAVRepositoryFactory.setup();
                SVNRepositoryFactoryImpl.setup();
                try {
                    repository = SVNRepositoryFactoryImpl.create(SVNURL.parseURIEncoded(this.url));
                    ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(this.username, this.password);
                    repository.setAuthenticationManager(authManager);
                } catch (SVNException e) {
                    e.printStackTrace();
                }
            }
            
            /**
      * 从SVN服务器获取最新版本的文件
      * @param filePath 相对于仓库根目录的路径
      * @param //outputStream 要输出的目标流，可以是文件流 FileOutputStream
      * @return 返回checkout文件的版本号
      * @throws Exception 可以自定义Exception
      */
            public long getFileFromSVN(String filePath, String outFileName) throws RuntimeException {
                return getFileFromSVN(filePath, outFileName, 0);
            }
            
            /**
      * 从SVN服务器获取文件
      * @param filePath 相对于仓库根目录的路径
      * @param //outputStream 要输出的目标流，可以是文件流 FileOutputStream
      * @param version 要checkout的版本号，当传入的版本号为0时，默认获取最新版本
      * @return 返回checkout文件的版本号
      * @throws Exception 可以自定义Exception
      */
            public long getFileFromSVN(String filePath, String outFileName, long version) throws RuntimeException {
                SVNNodeKind node = null;
                try {
                    if(version == 0){
                        version = repository.getLatestRevision();
                    }
                    node = repository.checkPath(filePath, version);
                } catch (SVNException e) {
                    throw new RuntimeException("SVN检测不到该文件:" + filePath, e);
                }
                if (node != SVNNodeKind.FILE) {
                    throw new RuntimeException(node.toString() + "不是文件");
                }
                SVNProperties properties = new SVNProperties();
                try {
                    OutputStream outputStream = new FileOutputStream(outFileName);
                    repository.getFile(filePath, version, properties, outputStream);
                    outputStream.close();
                } catch (SVNException e) {
                    throw new RuntimeException("获取SVN服务器中的" + filePath + "文件失败", e);
                } catch (IOException e) {
                    throw new RuntimeException("SVN check out file faild.", e);
                } 
                return Long.parseLong(properties.getStringValue("svn:entry:revision"));
            }
            
            /**
      * 获取目录下的所有文件和子目录
//      * @param res 包含目录参数的资源对象.参加{@link //Resource#getPath()}
      * @return 资源列表
      * @throws Exception
      */
            @SuppressWarnings("unchecked")
    public List<Resource> getChildren(Resource res) throws Exception {
                String path = res.getPath();
                Collection<SVNDirEntry> entries;
                List<Resource> result = new ArrayList<Resource>();
                try {
                    entries = repository.getDir(path, -1, null, (Collection) null);

                    for (SVNDirEntry entry : entries) {
                        if (containsSpecialFile(entry)) {
                            Resource resource = new Resource();
                            resource.setName(entry.getName());
                            resource.setPath(entry.getURL().getPath());
                            resource.setKind(entry.getKind() == SVNNodeKind.FILE);
                            result.add(resource);
                        }
                    }
                    System.out.println(result.size());
                    Iterator it=result.iterator();
                    while (it.hasNext()){
                        formatPtrln("path name: %s",it.next().toString());
                    }

                } catch (SVNException e) {
                    throw new Exception("获得" + path + "下级目录失败", e);
                }

                return result;
            }

    public static void formatPtrln(String format, Object... args) {
        System.out.println(String.format(format, args));
    }
            
            /**
      * 判断文件是否存在
      * @param entry 要判断的节点.参加{@link SVNDirEntry}
      * @return 
      * @throws Exception
      */

    private boolean containsSpecialFile(SVNDirEntry entry) throws Exception {
                if (entry.getKind() == SVNNodeKind.FILE) {
                    return true;
                } else if (entry.getKind() == SVNNodeKind.DIR) {
                    Collection<SVNDirEntry> entries;
                    String path = entry.getURL().getPath();
                    try {
                        entries = repository.getDir(path, -1, null, (Collection) null);
                        for (SVNDirEntry unit : entries) {
                            if (containsSpecialFile(unit)) {
                                return true;
                            }
                        }
                    } catch (SVNException e) {
                        //throw new Exception("获得" + path + "下级目录失败", e);
                    }

                    return false;
                }
                return false;
            }
            
            public static void main(String[] args) {
                SVNManager manager = new SVNManager("http://IP************", "username", "password");
                try {

                    //manager.getChildren(new Resource());
                    long startTime=System.currentTimeMillis();

                    manager.getSvnFileBaseInfoDto("/zt","",true);
                    //System.out.println(manager.getFileFromSVN("/zt/etax-fpyzdb-app/trunk/etax-fpyzdb-app/etax-fpyzdb-service/src/main/java/com/css/etax/fpyzdb/service/micro/FpyzdbCshszMicroService.java", "D:\\FpyzdbCshszMicroService.java"));
                    long endTime=System.currentTimeMillis();
                    System.out.println("共耗时"+(endTime-startTime));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
        //    public void testGetDir() {
//        try {
//            initialize();
//            Resource res = new Resource();
//            res.setPath("/app1/");
//            List<Resource> rs = getChildren(res);
//            for(Resource r : rs) {
//                System.out.println(r.getFile()?"file:":"directory:" + r.getPath());
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }



    /**
     * @Author: winterchen
     * @Description: 获取版本库中某一目录下的所有条目。可以根据参数选择是否进行递归
     * @Date: 2018/2/6
     * @param //repository
     * @param path  需要查找的svn路径（相对路径）前面不需要/
     * @param //typeEnum  文件类型
     * @param fileNameSearch    文件名过滤条件
     * @param isGetNext 是否递归 true  递归
     */

    public List<SVNDirEntry> getSvnFileBaseInfoDto(String path,
                                                          String fileNameSearch,
                                                          boolean isGetNext)throws SVNException {
        List<SVNDirEntry> result = new LinkedList<>();
        listEntries(path,result,fileNameSearch,isGetNext);
        System.out.println(result.size());
        Iterator it=result.iterator();
        while (it.hasNext()){
            formatPtrln("path name: %s",it.next().toString());
        }
        return result;
    }


/**
 * @Author: winterchen
 * @Description: 获取版本库中某一目录下的所有条目。可以根据参数选择是否进行递归
 * @Date: 2018/2/6
 * @param //repository
 * @param path  需要查找的svn路径（相对路径）前面不需要/
 * @param result    最后封装的容器
 * @param //typeEnum  文件类型
 * @param fileNameSearch    文件名过滤条件
 * @param isGetNext 是否递归 true  递归
 */

    public  void listEntries(String path, List<SVNDirEntry> result,
                                   String fileNameSearch,
                                   boolean isGetNext) throws SVNException {
        //获取版本库的path目录下的所有条目。参数－1表示是最新版本。
        Collection entries = repository.getDir(path, -1, null,
                (Collection) null);
        Iterator iterator = entries.iterator();

        while (iterator.hasNext()) {
            SVNDirEntry entry = (SVNDirEntry) iterator.next();
            boolean flag = true;

            if (entry.getKind() == SVNNodeKind.FILE) {
                //formatPtrln("current : %s",entry.getURL());
                if (entry.getURL().toString().contains("/service/local/") || entry.getURL().toString().contains("/service/micro/")) {

                    formatPtrln("current : %s",entry.getURL());
                    flag= true;
                }else{
                    flag=false;
                }

            } else if (entry.getKind() == SVNNodeKind.DIR) {
                flag=false;
            }
            //进行参数的匹配
//            if (typeEnum != null) {
//                if (!typeEnum.getValue().equals(SvnGetFileTypeEnum.DEFAULT.getValue())) {
//                    if (!entry.getKind().toString().equals(typeEnum.getValue())) {
//                        flag = false;
//                    }
//                }
//            }


            if (flag) { //如果两个条件都不为空，并且都通过了
                result.add(entry);
                formatPtrln("entity : %s",entry.getURL());
            }
            //判断是否需要进行递归
            if (isGetNext) {

    /*
     * 检查此条目是否为目录，如果为目录递归执行
     */

                if (entry.getKind() == SVNNodeKind.DIR) {
                    listEntries((path.equals("")) ? entry.getName()
                            : path + "/" + entry.getName(), result, fileNameSearch, isGetNext);
                }
            }
        }
    }






}

